package com.um.springboot.starter.controller;


import cn.hutool.core.util.StrUtil;
import com.um.springboot.starter.annotation.ActionLogRequired;
import com.um.springboot.starter.code.CommonCode;
import com.um.springboot.starter.entity.MultipartFileParam;
import com.um.springboot.starter.helper.SessionHelper;
import com.um.springboot.starter.orm.entity.Response;
import com.um.springboot.starter.properties.HshProperties;
import com.um.springboot.starter.service.FileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;


/**
 * @author 邓南辉
 * @date 2019/12/19
 * @copyright 广州优匠科技有限公司
 */
@Slf4j
@RestController
@Api(tags = "文件")
public class FileController {

    @Autowired
    FileService fileService;

    @Autowired
    HshProperties hshProperties;

    @Autowired
    SessionHelper sessionHelper;

    @ApiOperation(value = "上传文件")
    @PostMapping("/api/v1/file/upload_any_file")
    public Response uploadAnyFile(MultipartFileParam param){

        if (!hshProperties.getFile().isAllowUpload()) {
            return Response.failed(CommonCode.NotOpen);
        }
        if (!hshProperties.getFile().isAllowAnonymousUpload() && StrUtil.isBlank(sessionHelper.getSessionUserId())) {
            return Response.failed(CommonCode.LoginExpired);
        }

        return fileService.uploadAnyFile(param);
    }

    @ApiOperation(value = "上传私有文件")
    @PostMapping("/api/v1/file/upload_private_file")
    public Response uploadPrivateFile(MultipartFileParam param){

        if (!hshProperties.getFile().isAllowUpload()) {
            return Response.failed(CommonCode.NotOpen);
        }
        if (!hshProperties.getFile().isAllowAnonymousUpload() && StrUtil.isBlank(sessionHelper.getSessionUserId())) {
            return Response.failed(CommonCode.LoginExpired);
        }

        return fileService.uploadAnyFile(param, "private");
    }

    @ActionLogRequired
    @ApiOperation(value = "读取文件")
    @GetMapping("/api/v1/file/get_file")
    public void getFile(HttpServletRequest request, HttpServletResponse response, @RequestParam("path")String path) throws IOException {

        if (StrUtil.isBlank(path) || "null".equals(path) || "undefined".equals(path) || "/".equals(path)) {
            log.warn("空路径：{}", path);
            response.setStatus(HttpStatus.NOT_FOUND.value());
            return;
        }
        if (!path.startsWith("/")) {
            log.warn("无效路径：{}", path);
            response.setStatus(HttpStatus.NOT_FOUND.value());
            return;
        }
        if (path.contains("./")) {
            log.warn("非法路径：{}", path);
            response.setStatus(HttpStatus.NOT_FOUND.value());
            return;
        }

        Map<String,String> mapContentType = new Hashtable<>();
        mapContentType.put("gif","image/gif");
        mapContentType.put("jpeg","image/jpeg");
        mapContentType.put("png","image/png");
        mapContentType.put("jpg","image/jpeg");
        mapContentType.put("swf","application/x-shockwave-flash");
        mapContentType.put("flv","video/x-flv");
        mapContentType.put("mp4", "video/mp4");
        mapContentType.put("mp3","audio/mpeg");

        String filePath = "";
        if(hshProperties.getConfig().getPackaging().equals("jar") || !hshProperties.getFile().isRelative()){
            filePath = hshProperties.getFile().getPath()+path;
        }else{
            filePath = ResourceUtils.getURL("classpath:").getPath()+"static"+hshProperties.getFile().getPath()+path;
        }

        File file = new File(filePath);
        if(!file.exists()){
            log.warn("文件不存在：{}", filePath);
            response.setStatus(HttpStatus.NOT_FOUND.value());
            return;
        }
        if(file.isDirectory()){
            log.warn("路径是一个目录：{}", filePath);
            response.setStatus(HttpStatus.NOT_FOUND.value());
            return;
        }
        try{
            response.setHeader(HttpHeaders.ETAG, StrUtil.format("\"{}\"", file.length()));
            response.setDateHeader(HttpHeaders.LAST_MODIFIED, file.lastModified());
            if (response.getHeader(HttpHeaders.ETAG).equals(request.getHeader(HttpHeaders.IF_NONE_MATCH)) &&
                    response.getHeader(HttpHeaders.LAST_MODIFIED).equals(request.getHeader(HttpHeaders.IF_MODIFIED_SINCE))) {
                response.setStatus(HttpStatus.NOT_MODIFIED.value());
                return;
            }

            String suffix = file.getName();
            suffix = suffix.substring(suffix.lastIndexOf(".")+1);
            suffix = suffix.toLowerCase();

            if(mapContentType.containsKey(suffix)) {
                response.setContentType(mapContentType.get(suffix));
                response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "inline;filename=" + file.getName());
            }else{
                response.setContentType("application/octet-stream");
                response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName());
            }
            ServletOutputStream out = response.getOutputStream();
            FileInputStream in = new FileInputStream(file);
            response.setContentLength(in.available());
            byte[] contents = new byte[1024];
            while (in.read(contents) != -1) {
                out.write(contents);
            }
            in.close();
            out.flush();
            out.close();
        }catch(FileNotFoundException ex){
            log.error("文件不存在", ex);
        }
    }

    @ActionLogRequired
    @ApiOperation(value = "读取文件v2")
    @GetMapping("/api/v2/file/**")
    public void getFileV2(HttpServletRequest request, HttpServletResponse response) throws IOException {
        getFile(request, response, StrUtil.removePrefix(request.getRequestURI(), "/api/v2/file"));
    }

}
